'''
爬虫作业：爬取京东，淘宝等网站上的信息、商品信息、评论爬取(只做一种商品)
'''
from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from time import sleep
import requests as rq
import pandas as pd
from selenium.webdriver.common.keys import Keys
from bs4 import BeautifulSoup as bs 
from pymongo import MongoClient
from selenium.common.exceptions import NoSuchElementException

goods_content={}
data_list=[]
# 可视化界面  需要下载 chromedriver 及 Edge浏览器
browser = webdriver.Chrome()
browser.implicitly_wait(5)#隐式等待, 此处的隐式等待是针对Driver 每次执行命令的 最长执行时间也可以理解为超时时间，  一些人对此处有误解，认为是让Driver等一段时间，  确实某些时候能让Driver等一段时间， 但是影响是全局的，每次Driver执行 找不到元素都会等待此处设置的时间，  假设某处将此值设置的太长，必须在执行完成之后还原回来
#    wait = WebDriverWait(browser, 10)
def main():
#无界面
    # chrome_options = Options()
    # chrome_options.add_argument('--headless')
    # chrome_options.add_argument('--disable-gpu')
    # driver = webdriver.Chrome(options=chrome_options)
    
    # 获取用户商品的url
    urlList = input('请输入爬取商品url(以逗号分割):').strip()
    urlList = urlList.split(',')
#    url = 'https://item.jd.com/10037547970961.html#comment'


    for url in urlList:
        browser.get(url)
        get_good(browser)
    browser.close()

# 判断元素是否存在
def isElementPresent(browser, element):
        """
        用来判断元素标签是否存在，
        """
        try:
            browser.find_element_by_class_name(element)
        # 原文是except NoSuchElementException, e:
        except Exception :
            # 发生了NoSuchElementException异常，说明页面中未找到该元素，返回False
            return False
        else:
            # 没有发生异常，表示在页面中找到了该元素，返回True
            return True
## 获取评价
def get_evaluation(goods_detail):
    js = "var q=document.documentElement.scrollTop=5000"  #滚动 0 表示页顶 10000表示页底
    browser.execute_script(js) 
    sleep(3)
    js2 = "var q=document.documentElement.scrollTop=10000"
    browser.execute_script(js2) 
    sleep(3)
#    html= browser.page_source#获取源网页代码                              
    ## 评价详细信息
#    # 商品详情wrap
#    soup=bs(html,'lxml')
#    #根据class获取全部的li标签
#    li=soup.find_all(class_="comment-item")
#    goods_detail = browser
  
    comments = goods_detail.find_elements_by_class_name('comment-item')
    for comment in comments:
        picList = []
        username = comment.find_element_by_class_name('user-info').text.replace("\n", "")
        star = comment.find_element_by_class_name('comment-star').get_attribute('class')[-1] + '星级'
        word = comment.find_element_by_class_name('comment-con').text.replace("\n", "")
        # 调用isElementExist方法，判断元素是否存在
        flag = isElementPresent(comment, 'pic-list')
        if  flag:
            pics = comment.find_element_by_class_name('pic-list').find_elements_by_tag_name('a')
            for pic in pics:
                picList.append(pic.find_element_by_tag_name('img').get_attribute('src'))
        order_type = comment.find_element_by_class_name('order-info').find_elements_by_tag_name('span')[0].text
        order_date = comment.find_element_by_class_name('order-info').find_elements_by_tag_name('span')[-1].text

        likes = comment.find_element_by_class_name('J-nice').text
        sprite_comment = comment.find_element_by_class_name('comment-op').find_elements_by_tag_name('a')[2].text
#        goods_content={}
        goods_content['姓名']=username
        goods_content['星级']=star
        goods_content['评论内容']=word
        goods_content['评价图片地址']=picList
        goods_content['购买类型']=order_type
        goods_content['评价日期']=order_date
        goods_content['点赞人数']=likes
        goods_content['评论人数']=sprite_comment
        data_list.append(goods_content)
        print(goods_content)
#        print('页面总数为:{}'.format(len(data_list)))
        
def get_good(browser):
    goods_detail=browser
    ## 爬取评价信息
    get_evaluation(goods_detail)
    n =1
    # 爬取后面的页面
    while True:
        flag = isElementPresent(goods_detail, 'ui-pager-next')
        if flag:
            #翻页
            element = browser.find_element_by_class_name('ui-pager-next')
            browser.execute_script("arguments[0].click();", element)
            # 等待数据加载
            sleep(2)
            n = n+1
            ## 爬取评价信息
            get_evaluation(goods_detail)
            print('%d商品页数：' % n)
        else:
            print('爬取完毕，谢谢等候！')
            return
    print('商品总页数：%d' % n)
#def save_jdpinglun():
#保存到数据库
client=MongoClient()
#创建数据库
database=client['jdpinglun-shouji']
#创建集合
jd_pinglun=database['jd1']    
jd_pinglun.insert(goods_content)

main()
















































































































































###获得 京东每周一花的16个商品列表链接 这里可以定义函数，传入要抓取的关键字或页数，使其更加灵活
#urltrue_list=[]
##for i in range(16):
#url='https://search.jd.com/Search?keyword=华为手机&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq=华为手机&page=1'
#urltrue=request.unquote(url)
#urltrue_list.append(urltrue)
#
## 定义函数，获取商品列表页所有的商品详情链接
#browser = webdriver.Edge()
#browser.get(url) 
## 停顿
#wait = WebDriverWait(browser, 10)
#detail_urls = []
#
##定义函数，抓取商品一页的评论详情
#comment_details = []
#def com_info():
#    #获取评论详情的父阶
#    divs = browser.find_element_by_id('comment-0').find_elements_by_class_name('comment-item')
# 
#    #获取评论人群的会员分类
#    for each in divs:
#        if each.find_element_by_class_name('user-level').find_elements_by_tag_name('a'):
#            member='PLUS会员'
#        else:
#            member='普通会员'
#        # 评星
#        star=each.find_element_by_class_name('comment-column').\find_element_by_tag_name('div').get_attribute('class')
#        # 评语
#        comment=each.find_element_by_class_name('comment-column').find_element_by_tag_name('p').text
#        # 图片数或视频数
#        pic_num=len(each.find_element_by_class_name('comment-column').find_elements_by_tag_name('div')[1].\
#            find_elements_by_tag_name('a'))+len(each.find_element_by_class_name('comment-column').find_elements_by_tag_name('div')[1].\
#            find_elements_by_tag_name('video'))
# 
#        #订单详情
#        spans = each.find_element_by_class_name('order-info').find_elements_by_tag_name('span')
#        order=[]
#        for index, everyone in enumerate(spans):
#            order.append(spans[index].text)
# 
#        single=[member,star,comment,pic_num,order]
#        comment_details.append(single)
# 

##定义函数缓慢拖拽页面，使其加载完成
#def buffer():
#    for i in range(50):
#        sleep(0.3)
#        browser.execute_script('window.scrollBy(0,300)', '')
# 
##定义函数，抓取商品一页的评论详情
#comment_details = []
#def com_info():
#    #获取评论详情的父阶
#    divs = browser.find_element_by_id('comment-0').find_elements_by_class_name('comment-item')
# 
#    #获取评论人群的会员分类
#    for each in divs:
#        if each.find_element_by_class_name('user-level').find_elements_by_tag_name('a'):
#            member='PLUS会员'
#        else:
#            member='普通会员'
#        # 评星
#        star=each.find_element_by_class_name('comment-column').\
#            find_element_by_tag_name('div').get_attribute('class')
#        # 评语
#        comment=each.find_element_by_class_name('comment-column').find_element_by_tag_name('p').text
#        # 图片数或视频数
#        pic_num=len(each.find_element_by_class_name('comment-column').find_elements_by_tag_name('div')[1].\
#            find_elements_by_tag_name('a'))+len(each.find_element_by_class_name('comment-column').find_elements_by_tag_name('div')[1].\
#            find_elements_by_tag_name('video'))
# 
#        #订单详情
#        spans = each.find_element_by_class_name('order-info').find_elements_by_tag_name('span')
#        order=[]
#        for index, everyone in enumerate(spans):
#            order.append(spans[index].text)
# 
#        single=[member,star,comment,pic_num,order]
#        comment_details.append(single)
# 
# 
##获得 京东每周一花的16个商品列表链接 这里可以定义函数，传入要抓取的关键字或页数，使其更加灵活
#urltrue_list=[]
##for i in range(16):
#url='https://search.jd.com/Search?keyword=华为手机&enc=utf-8&qrst=1&rt=1&stop=1&vt=2&wq=华为手机&page=1'
#urltrue=request.unquote(url)
#urltrue_list.append(urltrue)
# 
## 定义函数，获取商品列表页所有的商品详情链接
#browser = webdriver.Edge()
#browser.get(url) 
## 停顿
#wait = WebDriverWait(browser, 10)
#detail_urls = []
#def get():
#    for each in urltrue_list:
#        browser.get(each)  # 遍历每个链接
#        sleep(2)
# 
#        global detail_urls
# 
#        buffer() # 缓冲，使页面加载完整
# 
#        info = browser.find_elements_by_class_name('gl-i-wrap')# 寻找商品链接的父阶
# 
#        for line in info:
#            # 获取商品列表页所有的商品链接
#            detail_url = line.find_element_by_class_name('p-img').find_element_by_tag_name('a').get_attribute('href')
#            detail_urls.append(detail_url)
#        sleep(2)
#        print(len(detail_urls)) # 查看长度确认是否抓取了60个连接
# 
#    return detail_urls  # 返回商品列表页所有的商品链接组成的列表
#get()
# 
##import os
##os.mkdir('txt1')
##os.chdir('txt1')
# 
# 
##遍历商品详情页，抓取目标数据，  这里可以对获取的每一个数据分开定义函数
#result=[]
#for index,each in enumerate(detail_urls): # 获取商品详情链接
#    #browser.maximize_window()# 最大化窗口
#    #获取源代码
#    html = browser.page_source
#    soup=bs(html,'lxml')
#    li=soup.find_all('li',class_='gl-item')
##    browser.get(each)
#    sleep(3)
# 
##    file = open(str(index)+'.txt1', 'w', encoding='utf-8')
# 
#    buffer()
# #.find(class_="p-name p-name-type-2").find('em').get_text()
#    #获取商品名称
#    title = li.find(class_="sku-name").get_text()
#    #获取价格(当前商品价格)
#    price = li.find(class_="p-price").find('span').get_text()
#    #获取系列商品总评论条数(有不同规格)
#    comment_num = li.find(class_="comment-count").find('a').get_text()
#    #获取品牌
#    brand = li.find(class_="parameter-brand").find('a').get_text()
#    #获取店名
#    shop_name = li.find(class_="p-parameter").find('li')[3].get_attribute('title')
#    #获取商品重量
#    weight = li.find(class_="p-parameter").find('li')[4].get_attribute('title')
#    #获取适用人群
#    user = li.find(class_="p-parameter").find('li')[5].get_attribute('title')
#    #获取分类
#    classify = li.find(class_="p-parameter").find('li')[6].get_attribute('title')
# 
#    buffer()
# 
#    #获取系列商品总好评度(有不同规格)
#    praise_degree=li.find(class_="percent-con").get_text()
#    #获取系列商品总评价标签(有不同规格)
#    tag_list = []
#    tags = li.find(class_=" tag-1")
#    for tag in tags:
#        tag_list.append(tag.text)
# 
#    li.find(class_="comm-curr-sku").send_keys(Keys.SPACE)  # 只看当前商品评价
# 
#    # 当前商品评论条数(单个)
#    single_comment_num = browser.find_element_by_class_name('filter-list').find_elements_by_tag_name('em')[0].text
#    # 当前商品评价标签
#    single_tags = browser.find_element_by_class_name('filter-list').find_elements_by_tag_name('li')[1:7]
#    single_tag_list = []
#    for each in single_tags:
#        det = each.find_element_by_tag_name('a').text
#        single_tag_list.append(det)
# 
#    detail=[title,price,brand,shop_name,weight,user,classify,comment_num,praise_degree,tag_list,single_comment_num,single_tag_list]
#    result+=detail # 将以上信息放到result列表中
# 
#    # 评论详情 包含用户会员等级、评星、评语、图片/视频数及订单详情
#    for i in range(50): #这里的50设置的有问题，有些商品评价没有这么多，需要写if判断来决定循环多少次
#        com_info()
#        browser.find_elements_by_class_name('ui-pager-next')[0].send_keys(Keys.ENTER) #点击评论的下一页
#        sleep(2)
# 
# 
#    print(comment_details)
#    con_text=comment_details
# 
#    # 存储   这里应该将存储单独定义函数
#    # 将所有的商品信息存入到一个excel中，便于做行业分析
#    # 将每个产品的评语分别存入txt文件便于做商品分析和用户分析
# 
##    file.write(str(comment_details)) #将每个商品的评语详情写入单独的txt文件
# 
#from openpyxl import Workbook
# 
#workbook=Workbook()
#sheet=workbook.active
#sheet.title='华为手机商品数据'
#sheet.append('商品名称，价格，品牌，店名，商品重量，适用人群，商品分类，系列商品总评论数，系列商品总好评度，系列商品总评价标签'
#             '当前商品评论条数，当前商品评价标签'.split(','))
##花材与产地因为信息不完整，没有抓取     如有分析需求再行补抓
#for each in result:
#    sheet.append(each)
# 
#workbook.save('华为手机商品数据.xlsx')